package main

/**
 * Created by IntelliJ IDEA.
 * User: koeppelad
 * Date: 4/24/11
 * Time: 3:47 PM
 * To change this template use File | Settings | File Templates.
 */


import org.lwjgl.Sys;
import lsystem.{ProductionRule, Variable, LSystem}
import org.lwjgl.opengl.{DisplayMode, Display}
import org.lwjgl.opengl.GL11._
import drawing.{HackedExampleDrawer}
import camera.Camera

class HackedExample {

  /**Game title */
  val GAME_TITLE = "My Game"

  /**Desired frame time */
  private val FRAMERATE = 60

  /**Exit the game */
  private var finished = false

  private var drawer: HackedExampleDrawer = null;

  private var lSystem: LSystem = null;

  private val iterations = 10

  private val dist = 20//250 * math.pow(.5, iterations)

  private val drawAngle = math.toRadians(22.5)

  val initState = "A"//"F"
  /*Set(new ProductionRule("F", "F[&+F]F[->F][->F][&F]"))*/
  val rules = Set(new ProductionRule("A", "[&FLA]/////[&bbFLA]///////[&FLA]"),//new ProductionRule("F", "FF/F+F^"))//"F[&+F]F[->F][->F][&F]"))
                  new ProductionRule("F", "S ///// F"),
                  new ProductionRule("S", "Fg LR"),
                  new ProductionRule("L", "[∧∧{-f+f+frr-|-f+f+f}]"))

  private var myCamera = new Camera();



  /**
   * Initialise the game
   * @throws Exception if init fails
   */
  def init(fullscreen: Boolean) {
    // Create a fullscreen window with 1:1 orthographic 2D projection (default)
    Display.setTitle(GAME_TITLE);
    Display.setFullscreen(fullscreen);

    // Enable vsync if we can (due to how OpenGL works, it cannot be guarenteed to always work)
    Display.setVSyncEnabled(true);

    // Create default display of 640x480
     Display.setDisplayMode(new DisplayMode(1000, 900))
    Display.create();
    resetLSystem()
  }

  private def resetLSystem() =
  {
      drawer = new HackedExampleDrawer()
     lSystem = {
      val moveForward = {() =>  drawer.draw(dist)}
      val turnLeft = {() => drawer.turnLeft(drawAngle)}
      val turnRight = {() => drawer.turnRight(drawAngle)}
      val pitchUp = {() => drawer.pitchUp(drawAngle)}
      val pitchDown = () => drawer.pitchDown(drawAngle)
      val rollLeft = () => drawer.rollLeft(drawAngle)
      val rollRight = () => drawer.rollRight(drawAngle)
      val turnAround = () => drawer.turnAround
      val push = () => drawer.push()
      val pop = () => drawer.pop()
      val doNothing = {() => }
      val incBlue = () => drawer.incBlue
      val decBlue = () => drawer.decBlue
      val incGreen = () => drawer.incGreen
      val decGreen = () => drawer.decGreen
      val incRed = () => drawer.incRed
      val decRed = () => drawer.decRed
      val incWidth = () => drawer.incrementWidth
      val decWidth = () => drawer.decrementWidth


      val vars = Set(new Variable("F", moveForward),
        new Variable("+", turnLeft),
        new Variable("-", turnRight),
        new Variable("&", pitchDown),
        new Variable("^", pitchUp),
        new Variable("\\", rollLeft),
        new Variable("/", rollRight),
        new Variable("|", turnAround),
        new Variable("[", push),
        new Variable("]", pop),
        new Variable("B", incBlue),
        new Variable("b", decBlue),
        new Variable("G", incGreen),
        new Variable("g", decGreen),
        new Variable("R", incRed),
        new Variable("r", decRed),
        new Variable("W", incWidth),
        new Variable("w", decWidth))

      drawer.turnLeft(math.Pi / 2)
      new LSystem(vars, rules, initState)
    }
  }

  /**
   * Runs the game (the "main loop")
   */
  def run() {


  resetLSystem()

  lSystem.iterate(iterations)
    myCamera.displaySize = drawer.getMax
    println("the max is: " + drawer.getMax)

    while (!finished) {
      // Always call Window.update(), all the time - it does some behind the
      // scenes work, and also displays the rendered output
      Display.update();

      // Check for close requests
      if (Display.isCloseRequested()) {
        finished = true;
      }

      // The window is in the foreground, so we should play the game
      else if (Display.isActive()) {
        render();
        Display.sync(FRAMERATE);
      }

      // The window is not in the foreground, so we can allow other stuff to run and
      // infrequently update
      else {
        try {
          Thread.sleep(100);
        } catch {
          case e: InterruptedException =>
        }

        // Only bother rendering if the window is visible or dirty
        if (Display.isVisible() || Display.isDirty()) {
          render();
        }
      }
    }
  }

 def render() {
    myCamera.drawBox
    // clear the screen.  Can be turned off for FUNTIMES
    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    lSystem.drawIt
  }

}

object RotationExample extends Application {
  override def main(args: Array[String]) = {
    /**Game title */
    val GAME_TITLE = "My Game"

    /**Desired frame time */
    val FRAMERATE = 60

    /**Exit the game */
    var finished = false

    /**Angle of rotating square */
    var angle: Float = 0
    val fullscreen = (args.length == 1 && args(0).equals("-fullscreen"));
    val game = new HackedExample
    try {
      game.init(fullscreen);
      game.run();
    } catch {
      case e: Exception => e.printStackTrace(System.err);
      Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
    } finally {
      Display.destroy
    }
    System.exit(0);
  }
}
